const express = require("express");
const router = express.Router();
const { Course, Category, User, Chapters } = require("../../models");

const { success, failure } = require("../../utils/response");
const { NotFound } = require('http-errors');
const { Op } = require("sequelize");
const { Conflict } = require("http-errors")

/**
 * 在一对多关联查询中，findAndCountAll的统计数会出错，需要加上  distinct:true
 * 在一堆多的关联查询中，如果要对关联数据进行排序，需要将order写到include的外面，并且指定清楚，是针对哪个模型进行的排序。
 * 在一些情况下（例如关联的模型较多），分被单独查询，比使用include更好
 */

// 查询所有课程信息
router.get("/", async (req, res) => {
  try {
    const query = req.query;

    const pageIndex = Math.abs(Number(query.pageIndex)) || 1;
    const pageSize = Math.abs(Number(query.pageSize)) || 10;
    const offset = (pageIndex - 1) * pageSize;

    const condition = {
      ...getCondition(),
      order: [["id", "DESC"]],
      limit: pageSize,
      offset,
    };

    const { count, rows } = await Course.findAndCountAll(condition);
    const data = {
      pagination: {
        total: count,
        pageIndex,
        pageSize,
      },
      data: rows,
    };
    success(res, "课程列表查询成功", data);
  } catch (error) {
    failure(res, error);
  }
});

// promise 查询首页数据
router.get("/promise",async(req,res)=>{
  try {
    const [recommendedCourses,likesCourses,introductoryCourses] = await Promise.all([
      // 焦点图（推荐的课程）
      Course.findAll({
        attributes:{exclude:['CategoryId','UserId','content']},
        include:[
          {
            model:Category,
            as:'category',
            attributes:['id','name']
          },
          {
            model:User,
            as:'user',
            attributes:['id','username','nickname','avatar','company']
          }
        ],
        where:{recommended:true},
        order:[['id','desc']],
        limit:10
      }),
      // 人气课程
      Course.findAll({
        attributes:{exclude:['CategoryId','UserId','content']},
        order:[['likesCount','desc'],['id','desc']],
        limit:10
      }),
      // 入门课程
      Course.findAll({
        attributes:{exclude:['Category','UserId','content']},
        where:{introductory:true},
        order:[['id','desc']],
        limit:10
      })
    ])
    success(res,'获取首页数据成功',{
      recommendedCourses,
      likesCourses,
      introductoryCourses
    })
  } catch (error) {
    failure(res,error)
  }
})

// 新增课程接口
router.post("/", async (req, res) => {
  try {
    const body = filterBody(req);
    const course = await Course.create(body);
    success(res, "添加成功！", course);
  } catch (error) {
    failure(res, error);
  }
});

// 删除课程接口
router.delete("/:id", async (req, res) => {
  try {
    const course = await getCourse(req);
    const count = await Chapters.count({ where: { courseId: req.params.id } });
    if (count > 0) {
      throw new Conflict("当前课程有章节，无法删除");
    }
    await course.destroy();
    success(res, "删除成功", null);
  } catch (error) {
    failure(res, error);
  }
});

// 修改课程信息
router.put("/:id", async (req, res) => {
  try {
    const body = await filterBody(req);
    const course = await getCourse(req);
    await course.update(body);
    success(res, "更新课程信息成功", course);
  } catch (error) {
    failure(res, error);
  }
});

// 课程模糊搜索
router.get("/search", async (req, res) => {
  try {
    const query = req.query;

    const pageIndex = Math.abs(Number(query.pageIndex)) || 1;
    const pageSize = Math.abs(Number(query.pageSize)) || 10;
    const offset = (pageIndex - 1) * pageSize;

    const condition = {
      where: {},
      ...getCondition(),
      order: [["id", "DESC"]],
      limit: pageSize,
      offset,
    };
    if (query.categoryId) {
      condition.where.categoryId = {
        [Op.eq]: query.categoryId,
      };
    }
    if (query.userId) {
      condition.where.userId = {
        [Op.eq]: query.userId,
      };
    }
    if (query.name) {
      condition.where.name = {
        [Op.like]: `%${query.name}%`,
      };
    }
    if (query.recommended) {
      condition.where.recommended = {
        [Op.eq]: query.recommended == "true",
      };
    }
    if (query.introductory) {
      condition.where.introductory = {
        [Op.eq]: query.introductory == "true",
      };
    }

    const { count, rows } = await Course.findAndCountAll(condition);

    const data = {
      pagination: {
        total: count,
        pageIndex,
        pageSize,
      },
      data: rows,
    };
    success(res, "查询成功", data);
  } catch (error) {
    failure(res, error);
  }
});

// 查询课程详细信息
// 使用include进行一对多的查询
router.get("/:id", async (req, res) => {
  try {
    const course = await getCourse(req);
    success(res, "获取详情成功", course);
  } catch (error) {
    failure(res, error);
  }
});

// 查询课程详细信息
router.get("/info/:id",async(req,res)=>{
  try {
    const {id} = req.params
    const condition = {
      attributes:{exclude:["CategoryId","UserId"]},
    }

    const course = await Course.findByPk(id,condition)
    if(!course){
      throw new NotFound(`ID:${id}的课程未找到。`)
    }

    // 查询课程关联的分类
    const category = await course.getCategory({
      attributes:['id','name']
    })

    // 查询课程关联的用户
    const user = await course.getUser({
      attributes:['id','usename','nickname','avatar','company']
    })

    // 查询课程关联的章节
    const chapters = await course.getChapters({
      attributes:['id','title','rank','createdAt'],
      order:[['rank','ASC'],['id','DESC']]
    })

    success(res,'查询课程成功',{course,category,user,chapters})
  } catch (error) {
    failure(res,error)
  }
})

// promise 查询课程详细信息
router.get("/promise/:id",async(req,res)=>{
  const {id} = req.params
  const condition = {
    attributes:{exclude:['CategoryId','UserId']},
  }

  const course = await Course.findAll(id,condition)
  if(!course){
    throw new NotFound(`ID:${id}的课程未找到`)
  }

  const [category,user,chapters] = Promise.all([
    course.getCategory({attributes:['id','name']}),
    course.getUser({attributes:['id','username','nickname','avatar','company']}),
    course.getChapter({attributes:['id','title','rank','createdAt'],order:[['rank','ASC'],['id','DESC']]})
  ])

  success(res,'查询成功',{course,category,user,chapters})
})

/**
 * 公共方法：过滤请求体
 * @param {*} req
 * @returns
 */
function filterBody(req) {
  const {
    categoryId,
    userId,
    name,
    image,
    recommended,
    introductory,
    content,
    likesCount,
    chaptersCount,
    free
  } = req.body;
  return {
    categoryId,
    userId,
    name,
    image,
    recommended,
    introductory,
    content,
    likesCount,
    chaptersCount,
    free
  };
}

/**
 * 公共方法：获取课程
 * @param {*} req
 * @returns
 */
async function getCourse(req) {
  const { id } = req.params;
  const condition = getCondition();
  const course = await Course.findByPk(id, condition);
  if (!course) {
    throw new NotFound("该课程不存在");
  }
  return course;
}

/**
 * 公共方法：关联分类、用户数据
 * @returns {{include: [{as: string, model, attributes: string[]}], attributes: {exclude: string[]}}}
 */
function getCondition() {
  return {
    // 用来在查询中去重
    distinct:true,
    attributes: { exclude: ["CategoryId", "UserId"] },
    include: [
      {
        model: Category,
        as: "category",
        attributes: ["id", "name"],
      },
      {
        model: User,
        as: "user",
        attributes: ["id", "username", "avatar",'nickname','company'],
      },
      {
        model:Chapter,
        as:'chapters',
        attributes:['id','title','rank','createdAt']
      }
    ],
    order:[
      [{model:Chapter,as:'chapters'},'rank','ASC'],
      [{model:Chapter,as:'chapters'},'id','DESC']
    ]
  };
}

module.exports = router;
